#include <GTL/gtlAll.h>
#include <iostream>

#include "tests/tinythread.h"
using namespace tthread;

GTL::Concurrency::Channel<int, 2> chan;
bool finished;

void Consumer(void * arg)
{
	int random = 100;
	do 
	{
		random = rand()%1000;
		printf("Giving %i\n", random);
		chan << random;
	} while (random);

	finished = true;
}

void Producer(void * arg)
{
	int random = 100;
	do 
	{
		printf("Reading...\n");
		chan >> random;
		printf("Got: %i\n", random);
	} while (random);

	finished = true;
}

bool test_func()
{
	char buffer[20];

	//buffer[50] = 'asdf';

	//return buffer[15];
	return false;
}
/*
struct Event : public GTL::AutoMember::AutoMember
{
	const char* EventName; 

	virtual int Call(int argument) = 0;
	virtual int GetBaseType() { return 'EVEN'; }
	virtual int GetType() { return 'even'; }
};

#define on(name) \
	struct __class_event_##name : public Event { \
		virtual uint32_t OnCreate() {\
			EventName = #name; return 0; \
		} \
		virtual int Call(int argument) { \
			self_type* w = (self_type*)this->mParent; \
			return w->On##name (argument); \
		} \
	} __object_event_##name; \
	int On##name (int argument)

struct State;

struct StateHolder : public GTL::AutoMember::AutoMember
{
	const char* StateName; 

	virtual int GetBaseType() { return 'STAT'; }
	virtual int GetType() { return 'stat'; }
	virtual void CreateState() {};

	virtual State* GetState() = 0;
};

struct State
{
	virtual int OnEnter(int arg) { return 0; }
	virtual int OnUpdate(int arg) { return 0; }
	virtual int OnDraw(int arg) { return 0; }
	virtual int OnEvent(int arg) { return 0; }
	virtual int OnLeave(int arg) { return 0; }
};

bool operator==(const State& st, const State* stptr) { return stptr == &st; }
bool operator==(const State* st, const State& stptr) { return st == &stptr; }

#define state(name) \
	struct __state_##name; \
	struct __state_##name##_Holder : public StateHolder \
	{ \
		State* TheState; \
		__state_##name##_Holder() { TheState = new __state_##name; } \
		State* operator->() { return TheState; } \
		operator State*() { return TheState; } \
		virtual State* GetState() { return TheState; } \
		\
		void Destroy() { delete TheState; } \
		~__state_##name##_Holder() { Destroy(); } \
	} name; \
	struct __state_##name : public State

class GameObject : public GTL::AutoMember::Producible
{
	GTL_DEFINE_PRODUCIBLE_OBJECT(GameObject)
public:
	State* CurrentState;

	Event* GetEvent(const char* event)
	{
		for (size_t i=0; i<this->mMembers.size(); i++)
			if (this->mMembers[i]->GetType() == 'even')
				return (Event*)this->mMembers[i];
		return 0;
	}

	int CallEvent(const char* event, int arg)
	{
#define declev(a) if (!strcmp(event, #a))	return this->CurrentState->On##a(arg);
		declev(Update);
		declev(Draw);
		declev(Enter);
		declev(Leave);
		declev(Event);
		for (size_t i=0; i<this->mMembers.size(); i++)
			if (this->mMembers[i]->GetType() == 'even')
			{
				Event* ev = (Event*)this->mMembers[i];
				if (!strcmp(ev->EventName, event))
					return ev->Call(arg);
			}
		return -1;
	}

	virtual int OnCreate() {
		for (size_t i=0; i<this->mMembers.size(); i++)
			if (this->mMembers[i]->GetType() == 'stat')
			{
				CurrentState = ((StateHolder*)this->mMembers[i])->GetState();
				return 0;
			}
		CurrentState = 0;
		return 0;
	}
	virtual int OnDestroy() { return 0; }
};

class Warrior : public GameObject
{
	GTL_DEFINE_PRODUCIBLE_OBJECT(Warrior)
public:
	on(Warrior, Damage)
	{
		if (CurrentState == Standing)
			printf("Argh! I've taken %i damage!\n", argument);
		return 0;
	}

	state(Standing)
	{
		virtual int OnUpdate(int arg)
		{
			printf("Come here, bitch!\n");

			return arg*2;
		}
	};

};
*/

class GameObject;

struct Event : public GTL::AutoMember::AutoMember
{

};

struct State
{
	std::map<std::string, Event*> Events;
};

#define state(name) \
struct __state_##name; \
struct __state_##name##_Holder : public GTL::AutoMember::AutoMember { \
	State* TheState; \
	__state_##name##_Holder() : AutoMember() { TheState = new __state_##name; GameObject* go = (GameObject*)mParent; go->SetCreatingState(0); } \
	virtual int GetType() { return 'stho'; } \
	virtual int GetBaseType() { return 'stho'; } \
	State* operator->() { return TheState; } \
	operator State*() { return TheState; } \
	virtual State* GetState() { return TheState; } \
	\
	void Destroy() { delete TheState; } \
	~__state_##name##_Holder() { Destroy(); } \
}; \
struct __state_##name : public State


class GameObject : public GTL::AutoMember::Producible
{
	GTL_DEFINE_PRODUCIBLE_OBJECT(GameObject)
private:
	State* mCreatingState;
public:
	void SetCreatingState(State* st) { mCreatingState = st; }

	struct EventMO : public GTL::AutoMember::AutoMember
	{
		virtual int GetType() { return 0; }
		virtual int GetBaseType() { return 0; }
		EventMO() : AutoMember()
		{
			printf("Event1\t\tMainObj\t\t%p\n", this);
		}
	} EventMOE;

	struct StateHolder1 : public GTL::AutoMember::AutoMember
	{
		StateHolder1() : AutoMember()
		{
			printf("State1\t\tMainObj\t\t%p\n", this);
		}

		struct Event1 : public GTL::AutoMember::AutoMember
		{
			virtual int GetType() { return 0; }
			virtual int GetBaseType() { return 0; }
			Event1() : AutoMember()
			{
				printf("Event1\t\tState1\t\t%p\n", this);
			}
		} Event1E;
		struct Event2 : public GTL::AutoMember::AutoMember
		{
			virtual int GetType() { return 0; }
			virtual int GetBaseType() { return 0; }
			Event2() : AutoMember()
			{
				printf("Event2\t\tState1\t\t%p\n", this);
			}
		} Event2E;

		virtual int GetBaseType() { return 'STAT'; }
		virtual int GetType() { return 'stat'; }
	} State1;

	struct EventMO3 : public GTL::AutoMember::AutoMember
	{
		virtual int GetType() { return 0; }
		virtual int GetBaseType() { return 0; }
		EventMO3() : AutoMember()
		{
			printf("Event3\t\tMainObj\t\t%p\n", this);
		}
	} EventMO3E;

	struct StateHolder2 : public GTL::AutoMember::AutoMember
	{
		StateHolder2() : AutoMember()
		{
			printf("State2\t\tMainObj\t\t%p\n", this);
		}

		struct StateHolderI1 : public GTL::AutoMember::AutoMember
		{
			StateHolderI1() : AutoMember()
			{
				printf("StateI1\t\tState2\t\t%p\n", this);
			}

			struct Event1 : public GTL::AutoMember::AutoMember { virtual int GetType() { return 0; } virtual int GetBaseType() { return 0; }
				Event1() : AutoMember()	{ printf("Event1\t\tStateI1\t\t%p\n", this);	}	} Event1E;
			struct Event2 : public GTL::AutoMember::AutoMember { virtual int GetType() { return 0; } virtual int GetBaseType() { return 0; }
				Event2() : AutoMember()	{ printf("Event2\t\tStateI1\t\t%p\n", this);	}	} Event2E;

			virtual int GetBaseType() { return 'STAT'; }
			virtual int GetType() { return 'stat'; }
		} StateI1;

		struct Event1 : public GTL::AutoMember::AutoMember
		{
			virtual int GetType() { return 0; }
			virtual int GetBaseType() { return 0; }
			Event1() : AutoMember()
			{
				printf("Event1\t\tState2\t\t%p\n", this);
			}
		} Event1E;

		struct StateHolderI2 : public GTL::AutoMember::AutoMember
		{
			StateHolderI2() : AutoMember()
			{
				printf("StateI2\t\tState2\t\t%p\n", this);
			}

			struct Event1 : public GTL::AutoMember::AutoMember { virtual int GetType() { return 0; } virtual int GetBaseType() { return 0; }
			Event1() : AutoMember()	{ printf("Event1\t\tStateI2\t\t%p\n", this);	}	} Event1E;
			struct Event2 : public GTL::AutoMember::AutoMember { virtual int GetType() { return 0; } virtual int GetBaseType() { return 0; }
			Event2() : AutoMember()	{ printf("Event2\t\tStateI2\t\t%p\n", this);	}	} Event2E;

			virtual int GetBaseType() { return 'STAT'; }
			virtual int GetType() { return 'stat'; }
		} StateI2;

		struct Event2 : public GTL::AutoMember::AutoMember
		{
			virtual int GetType() { return 0; }
			virtual int GetBaseType() { return 0; }
			Event2() : AutoMember()
			{
				printf("Event2\t\tState2\t\t%p\n", this);
			}
		} Event2E;

		struct StateHolderI3 : public GTL::AutoMember::AutoMember
		{
			StateHolderI3() : AutoMember()
			{
				printf("StateI3\t\tState2\t\t%p\n", this);
			}

			struct Event1 : public GTL::AutoMember::AutoMember { virtual int GetType() { return 0; } virtual int GetBaseType() { return 0; }
			Event1() : AutoMember()	{ printf("Event1\t\tStateI3\t\t%p\n", this);	}	} Event1E;
			struct Event2 : public GTL::AutoMember::AutoMember { virtual int GetType() { return 0; } virtual int GetBaseType() { return 0; }
			Event2() : AutoMember()	{ printf("Event2\t\tStateI3\t\t%p\n", this);	}	} Event2E;

			virtual int GetBaseType() { return 'STAT'; }
			virtual int GetType() { return 'stat'; }
		} StateI3;

		virtual int GetBaseType() { return 'STAT'; }
		virtual int GetType() { return 'stat'; }
	} State2;

	struct EventMO2 : public GTL::AutoMember::AutoMember
	{
		virtual int GetType() { return 0; }
		virtual int GetBaseType() { return 0; }
		EventMO2() : AutoMember()
		{
			printf("Event2\t\tMainObj\t\t%p\n", this);
		}
	} EventMO2E;

	virtual int OnCreate()
	{
		for (size_t i=0; i<mMembers.size(); i++)
			printf("%p\n", mMembers[i]);
		return 0;
	}
	virtual int OnDestroy()
	{
		return 0;
	}
};

int main()
{
	//finished = false;
	//thread consumer(Consumer, 0);
	//thread producer(Producer, 0);


	//Warrior* w = GTL::AutoMember::Producible::Produce<Warrior>();
	//printf("%i\n", w->CallEvent("Update", 15));

	GameObject* go = GTL::AutoMember::Producible::Produce<GameObject>();

	//while (!finished)
	{
		
	}

	//printf("%i\n",GTL::Memory::Duplicate(&consumer, 50));

  system("PAUSE");

  return 0;
}